package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.util.NumberUtil;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotUpdateException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class ProjectDelayApplyService {

	@Autowired
	private ProjectStakeholderDao projectStakeholderDao;
	
	private QProjectStakeholder $_projectStakeholder = QProjectStakeholder.projectStakeholder;
	
	@Autowired
	public void setProjectStakeholderDao(ProjectStakeholderDao projectStakeholderDao) {
		this.projectStakeholderDao = projectStakeholderDao;
	}

	@Autowired
	private ProjectDelayApplyDao projectDelayApplyDao;

	private QProjectDelayApply $ = QProjectDelayApply.projectDelayApply;

	@Autowired
	public void setProjectDelayApplyDao(
			ProjectDelayApplyDao projectDelayApplyDao) {
		this.projectDelayApplyDao = projectDelayApplyDao;
	}

	@Autowired
	private ProjectDao projectDao;
	
	private QProject $_project = QProject.project;
	
	@Autowired
	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}

	public List<ProjectDelayApply> findAll() {
		return ListUtil.toList(projectDelayApplyDao.findAll());
	}

	public List<ProjectDelayApply> findAll(Long projectId,
			Date originalFinishDateBegin, Date originalFinishDateEnd,
			Date targetFinishDateBegin, Date targetFinishDateEnd,
			Long applyPersonId, Date applyTimeBegin, Date applyTimeEnd,
			String applyReason, Long checkPersonId, Date checkTimeBegin,
			Date checkTimeEnd, String checkComment, Long ratifyPersonId,
			Date ratifyTimeBegin, Date ratifyTimeEnd, String ratifyComment,
			String status, String orderByAttribute) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}

		if (originalFinishDateBegin != null) {
			condition.and($.originalFinishDate.after(originalFinishDateBegin));
		}

		if (originalFinishDateEnd != null) {
			condition.and($.originalFinishDate.before(originalFinishDateEnd));
		}

		if (targetFinishDateBegin != null) {
			condition.and($.targetFinishDate.after(targetFinishDateBegin));
		}

		if (targetFinishDateEnd != null) {
			condition.and($.targetFinishDate.before(targetFinishDateEnd));
		}

		if (IdUtil.isNotEmpty(applyPersonId)) {
			condition.and($.applyPerson.id.eq(applyPersonId));
		}

		if (applyTimeBegin != null) {
			condition.and($.applyTime.after(applyTimeBegin));
		}

		if (applyTimeEnd != null) {
			condition.and($.applyTime.before(applyTimeEnd));
		}

		if (StringUtil.isNotEmpty(applyReason)) {
			condition.and($.applyReason.contains(applyReason));
		}

		if (IdUtil.isNotEmpty(checkPersonId)) {
			condition.and($.checkPerson.id.eq(checkPersonId));
		}

		if (checkTimeBegin != null) {
			condition.and($.checkTime.after(checkTimeBegin));
		}

		if (checkTimeEnd != null) {
			condition.and($.checkTime.before(checkTimeEnd));
		}

		if (StringUtil.isNotEmpty(checkComment)) {
			condition.and($.checkComment.contains(checkComment));
		}

		if (IdUtil.isNotEmpty(ratifyPersonId)) {
			condition.and($.ratifyPerson.id.eq(ratifyPersonId));
		}

		if (ratifyTimeBegin != null) {
			condition.and($.ratifyTime.after(ratifyTimeBegin));
		}

		if (ratifyTimeEnd != null) {
			condition.and($.ratifyTime.before(ratifyTimeEnd));
		}

		if (StringUtil.isNotEmpty(ratifyComment)) {
			condition.and($.ratifyComment.contains(ratifyComment));
		}

		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}

		return ListUtil.toList(projectDelayApplyDao.findAll(condition));
	}

	public Page<ProjectDelayApply> findAll(Long projectId,
			Date originalFinishDateBegin, Date originalFinishDateEnd,
			Date targetFinishDateBegin, Date targetFinishDateEnd,
			Long applyPersonId, Date applyTimeBegin, Date applyTimeEnd,
			String applyReason, Long checkPersonId, Date checkTimeBegin,
			Date checkTimeEnd, String checkComment, Long ratifyPersonId,
			Date ratifyTimeBegin, Date ratifyTimeEnd, String ratifyComment,
			String status, int pageNumber, int pageSize, String sortAttribute,
			String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if (IdUtil.isNotEmpty(projectId)) {
			condition.and($.project.id.eq(projectId));
		}
		if (originalFinishDateBegin != null) {
			condition.and($.originalFinishDate.after(originalFinishDateBegin));
		}

		if (originalFinishDateEnd != null) {
			condition.and($.originalFinishDate.before(originalFinishDateEnd));
		}
		if (targetFinishDateBegin != null) {
			condition.and($.targetFinishDate.after(targetFinishDateBegin));
		}

		if (targetFinishDateEnd != null) {
			condition.and($.targetFinishDate.before(targetFinishDateEnd));
		}
		if (IdUtil.isNotEmpty(applyPersonId)) {
			condition.and($.applyPerson.id.eq(applyPersonId));
		}
		if (applyTimeBegin != null) {
			condition.and($.applyTime.after(applyTimeBegin));
		}

		if (applyTimeEnd != null) {
			condition.and($.applyTime.before(applyTimeEnd));
		}
		if (StringUtil.isNotEmpty(applyReason)) {
			condition.and($.applyReason.contains(applyReason));
		}
		if (IdUtil.isNotEmpty(checkPersonId)) {
			condition.and($.checkPerson.id.eq(checkPersonId));
		}
		if (checkTimeBegin != null) {
			condition.and($.checkTime.after(checkTimeBegin));
		}

		if (checkTimeEnd != null) {
			condition.and($.checkTime.before(checkTimeEnd));
		}
		if (StringUtil.isNotEmpty(checkComment)) {
			condition.and($.checkComment.contains(checkComment));
		}
		if (IdUtil.isNotEmpty(ratifyPersonId)) {
			condition.and($.ratifyPerson.id.eq(ratifyPersonId));
		}
		if (ratifyTimeBegin != null) {
			condition.and($.ratifyTime.after(ratifyTimeBegin));
		}

		if (ratifyTimeEnd != null) {
			condition.and($.ratifyTime.before(ratifyTimeEnd));
		}
		if (StringUtil.isNotEmpty(ratifyComment)) {
			condition.and($.ratifyComment.contains(ratifyComment));
		}
		if (StringUtil.isNotEmpty(status)) {
			condition.and($.status.contains(status));
		}

		Sort sortObject = null;
		if (StringUtil.isEmpty(sortAttribute)) {
			sortObject = new Sort(Direction.DESC, "id");
		} else {
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),
					sortAttribute);
		}

		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize,
				sortObject);
		return projectDelayApplyDao.findAll(condition, pageRequest);
	}

	public void deleteProjectDelayApply(Long id) {
		projectDelayApplyDao.delete(id);
	}

	public void saveProjectDelayApply(ProjectDelayApply projectDelayApply) {
		if(null == projectDelayApply.getApplyTime()){
			projectDelayApply.setApplyTime(DateUtil.nowDate());
		}
		
		Project project = this.projectDao.findOne(projectDelayApply.getProject().getId());
		project.setStatus(projectDelayApply.getProject().getStatus());
		this.projectDao.save(project);
		
		projectDelayApplyDao.save(projectDelayApply);
	}

	public List<ProjectDelayApply> findByStatus(People people, Long projectStakeholderType, String status) {
		BooleanBuilder condition = new BooleanBuilder();
		condition.and(this.$_projectStakeholder.personID.eq(people.getId()));
		condition.and(this.$_projectStakeholder.projectStakeholderType.id.eq(projectStakeholderType));
		List<ProjectStakeholder> projectStakeholders = ListUtil.toList(this.projectStakeholderDao.findAll(condition));
		Set<Long> projectIds = new HashSet<Long>();
		for (ProjectStakeholder projectStakeholder : projectStakeholders) {
			projectIds.add(projectStakeholder.getProject().getId());
		}

		if(!projectIds.isEmpty()){
			condition = new BooleanBuilder();
			condition.and(this.$.project.id.in(projectIds));
			if (StringUtil.isNotEmpty(status)) {
				condition.and($.status.eq(status));
			}
			return ListUtil.toList(projectDelayApplyDao.findAll(condition));
		}
		return null;
	}

	public void ratifyProjectDelayApply(ProjectDelayApply projectDelayApply) throws CannotUpdateException {
		ProjectDelayApply sourceProjectDelayApply = this.projectDelayApplyDao.findOne(projectDelayApply.getId());
		if(!ProcessStatus.EXAMINE_SUCCESS.equals(sourceProjectDelayApply.getStatus())){
			throw new CannotUpdateException("您审批的项目延期发生变化，请刷新后再操作！");
		}
		sourceProjectDelayApply.setStatus(projectDelayApply.getStatus());
		sourceProjectDelayApply.setRatifyPerson(projectDelayApply.getRatifyPerson());
		sourceProjectDelayApply.setRatifyTime(DateUtil.nowDate());
		sourceProjectDelayApply.setRatifyComment(projectDelayApply.getRatifyComment());
		
		Project project = sourceProjectDelayApply.getProject();
		if(ProcessStatus.VERIFY_SUCCESS.equals(projectDelayApply.getStatus())){
			project.setPlanFinishDate(sourceProjectDelayApply.getTargetFinishDate());
			project.setPlanFinishDateChangeCount(NumberUtil.transition(project.getPlanFinishDateChangeCount()) + 1);
		}
		project.setStatus(projectDelayApply.getProject().getStatus());
		
		this.projectDelayApplyDao.save(sourceProjectDelayApply);
		this.projectDao.save(project);
	}

	public void revocationDelayApplyProjectDelayApply(ProjectDelayApply projectDelayApply) throws CannotUpdateException {
		ProjectDelayApply sourceProjectDelayApply = this.projectDelayApplyDao.findOne(projectDelayApply.getId());
		if(!ProcessStatus.DELAY_APPLY.equals(sourceProjectDelayApply.getStatus())){
			throw new CannotUpdateException("项目延期申请已被处理，请刷新后再操作！");
		}
		sourceProjectDelayApply.setStatus(projectDelayApply.getStatus());
		sourceProjectDelayApply.setApplyTime(DateUtil.nowDate());
		
		Project project = sourceProjectDelayApply.getProject();
		project.setStatus(projectDelayApply.getProject().getStatus());
		
		this.projectDelayApplyDao.save(sourceProjectDelayApply);
		this.projectDao.save(project);
	}

	public void checkProjectDelayApply(ProjectDelayApply projectDelayApply) throws CannotUpdateException {
		ProjectDelayApply sourceProjectDelayApply = this.projectDelayApplyDao.findOne(projectDelayApply.getId());
		if(!ProcessStatus.DELAY_APPLY.equals(sourceProjectDelayApply.getStatus())){
			throw new CannotUpdateException("您处理的项目延期已发生变化，请刷新后再操作！");
		}
		sourceProjectDelayApply.setCheckPerson(projectDelayApply.getCheckPerson());
		sourceProjectDelayApply.setCheckTime(DateUtil.nowDate());
		sourceProjectDelayApply.setCheckComment(projectDelayApply.getCheckComment());
		sourceProjectDelayApply.setStatus(projectDelayApply.getStatus());
		
		if(ProcessStatus.EXAMINE_FAIL.equals(projectDelayApply.getStatus())){
			Project project = sourceProjectDelayApply.getProject();
			project.setStatus(projectDelayApply.getProject().getStatus());
			
			this.projectDao.save(project);
		}
		this.projectDelayApplyDao.save(sourceProjectDelayApply);
	}

	public ProjectDelayApply findOne(Long id) {
		return this.projectDelayApplyDao.findOne(id);
	}

}
